package com.page.dao.impl;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.Proxy;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import com.page.common.vo.HostVO;
import com.page.common.vo.ServerStatusVO;
import com.page.conf.Config;
import com.page.dao.ServerStatusDao;

/**
 * @Package com.page.dao.impl
 * @File ServerStatus.java
 * @author shuxin.zheng@net263.com
 * @date 2014-12-21 上午11:03:51
 */

public class ServerStatusDaoImpl implements ServerStatusDao {

    public List<ServerStatusVO> getServerStatus() {
        List<ServerStatusVO> statusList = new ArrayList<ServerStatusVO>();
        String urlString = Config.getInstance().getUrl();
        HostVO manager = Config.getInstance().getManager();

        URL url;
        try {
            url = new URL(urlString);
        } catch (MalformedURLException e) {
            e.printStackTrace();
            return statusList;
        }

        HttpURLConnection connection;
        Proxy proxy = null;
        try {
            proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(
                    InetAddress.getByName(manager.getIP()), manager.getPort()));
        } catch (UnknownHostException e1) {
            e1.printStackTrace();
            return statusList;
        }

        try {
            connection = (HttpURLConnection) url.openConnection(proxy);
        } catch (IOException e) {
            e.printStackTrace();
            return statusList;
        }

        connection.setReadTimeout(manager.getSoTimeout());
        connection.setConnectTimeout(manager.getConnectTimeout());

        try {
            connection.setRequestMethod("GET");
        } catch (ProtocolException e1) {
            e1.printStackTrace();
            return statusList;
        }
        connection.setRequestProperty("accept", "*/*");
        connection.setRequestProperty("Connection", "close");
        connection.setRequestProperty("user-agent",
                "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");

        try {
            connection.connect();
        } catch (IOException e) {
            e.printStackTrace();
            return statusList;
        }

        StringBuffer buffer = new StringBuffer();
        try {
            InputStream in = connection.getInputStream();
            byte[] buf = new byte[8192];
            int ret;
            while ((ret = in.read(buf)) > 0) {
                buffer.append(new String(buf, 0, ret, "UTF-8"));
            }
            in.close();

        } catch (IOException e) {
            e.printStackTrace();
            return statusList;
        }

        return parseFromXml(statusList, buffer.toString());
    }

    @SuppressWarnings("unchecked")
    public List<ServerStatusVO> parseFromXml(List<ServerStatusVO> statusList,
            String data) {
        Document document;
        try {
            document = DocumentHelper.parseText(data);
        } catch (DocumentException e) {
            e.printStackTrace();
            return statusList;
        }

        /**
         * 数据格式
         * <servers>
         *   <server conns='xxx' used='xxx' qlen='xxx' max_threads='xxx'
         *    curr_threads='xxx' busy_threads='xxx' ip='xxx' load='xxx'>
         *    <proc>
         *      <conns>xxx</conns>
         *      <used>xxx</used>
         *      <pid>xxx</pid>
         *      <max_threads>xxx</max_threads>
         *      <curr_threads>xxx</curr_threads>
         *      <busy_threads>xxx</busy_threads>
         *      <qlen>xxx</qlen>
         *      <type>xxx</type>
         *    </proc>
         *   </server>
         * </servers>
         */

        int conns, used, qlen, maxThreads, currThreads, busyThreads;
        double load;
        String addr;

        Element root = document.getRootElement();
        for (Iterator<Element> it = root.elementIterator(); it.hasNext();) {
            Element el = it.next();
            String name = el.getName();
            if (!name.equalsIgnoreCase("server"))
                continue;

            String attrValue = el.attributeValue("conns");
            if (attrValue == null)
                continue;
            conns = Integer.parseInt(attrValue);

            attrValue = el.attributeValue("used");
            if (attrValue == null)
                continue;
            used = Integer.parseInt(attrValue);

            attrValue = el.attributeValue("qlen");
            if (attrValue == null)
                continue;
            qlen = Integer.parseInt(attrValue);

            attrValue = el.attributeValue("max_threads");
            if (attrValue == null)
                continue;
            maxThreads = Integer.parseInt(attrValue);

            attrValue = el.attributeValue("curr_threads");
            if (attrValue == null)
                continue;
            currThreads = Integer.parseInt(attrValue);

            attrValue = el.attributeValue("busy_threads");
            if (attrValue == null)
                continue;
            busyThreads = Integer.parseInt(attrValue);

            attrValue = el.attributeValue("load");
            if (attrValue == null)
                continue;
            load = Double.parseDouble(attrValue);

            addr = el.attributeValue("addr");
            if (addr == null)
                continue;

            ServerStatusVO statusVO = new ServerStatusVO();
            statusVO.setConns(conns);
            statusVO.setUsed(used);
            statusVO.setMaxThreads(maxThreads);
            statusVO.setCurrThreads(currThreads);
            statusVO.setBusyThreads(busyThreads);
            statusVO.setQlen(qlen);
            statusVO.setLoad(load);
            statusVO.setAddr(addr);

            statusList.add(statusVO);
        }

        return statusList;
    }

    /////////////////////////////////////////////////////////////////////////
    
    public static void main(String[] args) {
        List<ServerStatusVO> statusList = new ArrayList<ServerStatusVO>();
        String data = "<?xml version='1.0'?><servers>"
            + "<server conns='10' used='100' qlen='1' max_threads='10' "
            + "curr_threads='1' busy_threads='100' ip='127.0.0.1' load='5.5'>"
            + "<proc> <conns>xxx</conns>"
            + "<used>xxx</used>"
            + "<pid>xxx</pid>"
            + "<max_threads>xxx</max_threads>"
            + "<curr_threads>xxx</curr_threads>"
            + "<busy_threads>xxx</busy_threads>"
            + "<qlen>xxx</qlen>"
            + "<type />"
            + "</proc>"
            + "</server>"
            + "</servers>";
        
        ServerStatusDaoImpl statusDao = new ServerStatusDaoImpl();
        statusDao.parseFromXml(statusList, data);
        for (ServerStatusVO status : statusList) {
            System.out.println("conns: " + status.getConns()
                    + ", used: " + status.getUsed()
                    + ", max_threads: " + status.getMaxThreads()
                    + ", curr_threads: " + status.getCurrThreads()
                    + ", busy_threads: " + status.getBusyThreads()
                    + ", qlen: " + status.getQlen()
                    + ", load: " + status.getLoad());
        }
    }
}
